From: Aditya Bhargava Date: Mon, 29 Sep 2025 22:05:19 +0000 (-0400) Subject: acme.sh: add `abort` service command and improve interactive messages X-Git-Url: http://git.openwrt.org/%22https:/collectd.org//%22http:/www.crowdsec.net/%22/%22https:/collectd.org/%22http:/www.crowdsec.net/%22?a=commitdiff_plain;h=fbf38647fda3e1577257297d5815714814813abf;p=feed%2Fpackages.git acme.sh: add `abort` service command and improve interactive messages For runs started interactively, improve messaging and allow a run to be aborted with `service acme abort`. Signed-off-by: Aditya Bhargava --- diff --git a/net/acme-acmesh/files/hook.sh b/net/acme-acmesh/files/hook.sh index 0bca1f19aa..1b6a04feaa 100644 --- a/net/acme-acmesh/files/hook.sh +++ b/net/acme-acmesh/files/hook.sh @@ -39,6 +39,53 @@ link_certs() { fi } +handle_signal() { + local notify_op=$1 + local label_op=$2 + wait_notify() { + # wait for acme.sh child job to die, *then* notify about status + wait + log warn "$label_op aborted: $main_domain" + $NOTIFY "${notify_op}-failed" + exit 1 + } + + trap wait_notify TERM + # try to kill the cgroup + local cgroup=$(cut -d : -f 3 /proc/$$/cgroup) + if [[ "$cgroup" == '/services/acme/*' ]]; then + # send SIGTERM to all processes in this process's cgroup. this + # relies on procd's having set up the cgroup for the instance. + read -r -d '' pids < /sys/fs/cgroup${cgroup}/cgroup.procs + kill -TERM $pids 2> /dev/null + fi + + # if we're here, either the cgroup wasn't as exected to be set up by + # procd or killing the cgroup PIDs failed. try to kill the process + # group, assuming this process is the group leader. this is actually + # unlikely since procd doesn't set service PGIDs (so they aren't group + # leaders). + kill -TERM -$$ 2> /dev/null + + # if we're here, cgroup-based killing was avoided or didn't work and + # PGID-based killing didn't work. fall back to the raciest option. + trap "" TERM + term_descendants() { + local pids=$@ + local pid= + # `pgrep -P` returns nothing if given a non-existent PID + # (even if the PID has live children), so children must + # be killed first + for pid in $pids; do + term_descendants $(pgrep -P "$pid") + kill -TERM "$pid" 2> /dev/null + done + } + term_descendants $(jobs -p) + + wait_notify +} + case $1 in get) set -- @@ -67,10 +114,11 @@ get) else set -- "$@" --renew --home "$state_dir" -d "$main_domain" log info "$ACME $*" - trap 'log err "Renew failed: SIGINT";$NOTIFY renew-failed;exit 1' INT - $ACME "$@" + trap "handle_signal renew Renewal" INT TERM + $ACME "$@" & + wait $! status=$? - trap - INT + trap - INT TERM case $status in 0) @@ -141,12 +189,13 @@ get) set -- "$@" --issue --home "$state_dir" log info "$ACME $*" - trap 'log err "Issue failed: SIGINT";$NOTIFY issue-failed;exit 1' INT + trap "handle_signal issue Issuance" INT TERM "$ACME" "$@" \ --pre-hook "$NOTIFY prepare" \ - --renew-hook "$NOTIFY renewed" + --renew-hook "$NOTIFY renewed" & + wait $! status=$? - trap - INT + trap - INT TERM case $status in 0) diff --git a/net/acme-common/files/acme.init b/net/acme-common/files/acme.init index 5d441f2325..cb2b5505d2 100644 --- a/net/acme-common/files/acme.init +++ b/net/acme-common/files/acme.init @@ -13,7 +13,8 @@ LOG_TAG=acme # shellcheck source=net/acme/files/functions.sh . "$IPKG_INSTROOT/usr/lib/acme/functions.sh" -extra_command "renew" "Start a certificate renew" +extra_command "abort" "Abort running certificate issuances/renewals" +extra_command "renew" "Run certificate issuances/renewals" delete_nft_rule() { if [ "$NFT_HANDLE" ]; then @@ -136,6 +137,7 @@ get_cert() { load_options "$section" load_credentials() { + # use `eval` to correctly strip quotes around credential values eval procd_append_param env "$1" } config_list_foreach "$section" credentials load_credentials @@ -175,15 +177,20 @@ start_service() { } service_started() { - echo "Certificate renewal enabled via cron. To renew now, run '/etc/init.d/acme renew'." + echo 'Nightly certificate renewal enabled. To renew now, run `service acme renew`.' } stop_service() { sed -i '\|/etc/init.d/acme|d' /etc/crontabs/root + running && stop_aborted="Running certificate renewal(s) aborted and a" } service_stopped() { - echo "Certificate renewal is disabled." + if enabled; then + untilboot=' until next boot. To disable permanently, run `service acme disable`' + fi + echo "${stop_aborted:-A}utomatic nightly renewal disabled$untilboot." + echo 'To re-enable nightly renewal, run `service acme start`. To issue/renew now, run `service acme renew`.' } service_triggers() { @@ -201,5 +208,21 @@ load_and_run() { } renew() { + echo "Starting certificate issuance/renewal in the background; see system log for progress." + echo 'Issuances/renewals can be aborted with `service acme abort`.' rc_procd load_and_run } + +abort() { + procd_lock + if running "$@"; then + procd_kill "$(basename ${basescript:-$initscript})" "$1" + echo "Aborting certificate issuance(s)/renewal(s); see system log for confirmation." + elif [ -z "$1" ]; then + echo "No certificate issuances/renewals running to abort!" + exit 1 + else + echo "No certificate issuance/renewal \"$1\" running to abort!" + exit 1 + fi +}